import {
  BadRequestException,
  ForbiddenException,
  Injectable,
  InternalServerErrorException,
  NotFoundException,
} from '@nestjs/common';
import { CreateVideoDto } from './dto/create-video.dto';
import { Video } from 'src/entities/video.entity';
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
import { DataSource, Repository } from 'typeorm';
import { ConfigService } from '@nestjs/config';
import * as qiniu from 'qiniu';
import { QiniuService } from '../qiniu/qiniu.service';
import { VideoStatus } from 'src/constant/VideoStatus';
import { LikeService } from '../like/like.service';
import Redis from 'ioredis';
import { InjectRedis } from '@nestjs-modules/ioredis';
import { VideoCategory } from 'src/entities/video-category.entity';
import { GetUserVideosDto, VideoStatusFilter } from './dto/get-user-videos.dto';
import { UpdateVideoDto } from './dto/update-video.dto';
import { ResubmitVideoDto } from './dto/resubmit-video.dto';
import { FavoriteVideo } from 'src/entities/favorite-videos.entity';
import { Comment } from 'src/entities/comment.entity';
import { FollowService } from '../follow/follow.service';
import { QueryVideosDto } from './dto/query-videos.dto';
import { User } from 'src/entities/user.entity';
@Injectable()
export class VideoService {
  private qiniuMac: qiniu.auth.digest.Mac;

  constructor(
    @InjectRepository(Video)
    private videoRepository: Repository<Video>,
    @InjectRepository(VideoCategory)
    private videoCategoryRepository: Repository<VideoCategory>,
    @InjectRepository(User)
    private userRepository: Repository<User>,
    @InjectDataSource()
    private dataSource: DataSource, // 添加DataSource依赖
    private configService: ConfigService,
    private qiniuService: QiniuService,
    private likeService: LikeService,
    private followService: FollowService, // 添加FollowService依赖
    @InjectRedis() private readonly redis: Redis,
  ) {
    this.qiniuMac = new qiniu.auth.digest.Mac(
      configService.get('QINIU_ACCESS_KEY'),
      configService.get('QINIU_SECRET_KEY'),
    );
  }

  /**
   * 管理员审核通过视频
   * @param id 视频ID
   * @returns 操作结果
   */
  async approveVideo(id: number) {
    // 查找视频
    const video = await this.videoRepository.findOne({
      where: { video_id: id, is_delete: 0 },
      relations: ['user'],
    });

    // 视频不存在或已删除
    if (!video) {
      throw new NotFoundException('视频不存在或已删除');
    }

    // 只有人工审核状态的视频才能设置为通过
    if (video.status !== 'manualReview') {
      throw new BadRequestException('只有人工审核状态的视频才能被设置为通过');
    }

    // 更新视频状态
    video.status = VideoStatus.APPROVED;
    // 清空审核原因（如果有）
    video.audit_reason = null;

    // 保存更新
    await this.videoRepository.save(video);

    return {
      code: 200,
      message: '视频已审核通过',
      data: {
        video_id: video.video_id,
        title: video.title,
        status: video.status,
      },
    };
  }

  /**
   * 高级分页查询视频
   */
  async queryVideos(queryDto: QueryVideosDto) {
    const {
      pageNum = 1,
      pageSize = 10,
      videoId,
      userId,
      username,
      title,
      status,
      categoryName,
    } = queryDto;

    const skip = (pageNum - 1) * pageSize;

    // 构建查询
    const queryBuilder = this.videoRepository
      .createQueryBuilder('video')
      .leftJoinAndSelect('video.user', 'user')
      .leftJoinAndSelect('video.category', 'category')
      .where('video.is_delete = :isDelete', { isDelete: 0 });

    // 添加各种条件
    if (videoId) {
      queryBuilder.andWhere('video.video_id = :videoId', { videoId });
    }

    if (userId) {
      queryBuilder.andWhere('user.id = :userId', { userId });
    }

    if (username) {
      queryBuilder.andWhere('user.username LIKE :userName', {
        userName: `%${username}%`,
      });
    }

    if (title) {
      queryBuilder.andWhere('video.title LIKE :title', { title: `%${title}%` });
    }

    if (status) {
      queryBuilder.andWhere('video.status = :status', { status });
    }

    if (categoryName) {
      queryBuilder.andWhere('category.name LIKE :categoryName', {
        categoryName: `%${categoryName}%`,
      });
    }

    // 执行查询
    const [videos, total] = await queryBuilder
      .orderBy('video.created_at', 'DESC')
      .skip(skip)
      .take(pageSize)
      .getManyAndCount();

    // 返回结果
    return {
      items: videos.map((video) => ({
        id: video.video_id,
        title: video.title,
        description: video.description,
        coverUrl: video.cover_url,
        ossUrl: video.oss_url,
        duration: video.duration,
        status: video.status,
        createdAt: video.created_at,
        user: {
          id: video.user?.id,
          username: video.user?.username,
          avatar: video.user?.avatar,
        },
        category: video.category
          ? {
              id: video.category.id,
              name: video.category.name,
            }
          : null,
        likesCount: video.likes_count,
      })),
      meta: {
        totalItems: total,
        itemCount: videos.length,
        itemsPerPage: pageSize,
        totalPages: Math.ceil(total / pageSize),
        currentPage: pageNum,
      },
    };
  }

  /**
   * 管理员更新视频信息
   * @param id 视频ID
   * @param updateVideoDto 更新视频DTO
   */
  async adminUpdateVideo(id: number, updateVideoDto: UpdateVideoDto) {
    // 查找视频
    const video = await this.videoRepository.findOne({
      where: { video_id: id, is_delete: 0 },
      relations: ['user', 'category'],
    });

    // 视频不存在或已删除
    if (!video) {
      throw new NotFoundException('视频不存在或已删除');
    }

    // 更新视频信息
    if (updateVideoDto.title) {
      video.title = updateVideoDto.title;
    }

    if (updateVideoDto.description) {
      video.description = updateVideoDto.description;
    }

    // 更新分类
    if (updateVideoDto.categoryId) {
      const category = await this.videoCategoryRepository.findOne({
        where: { id: updateVideoDto.categoryId },
      });

      if (!category) {
        throw new BadRequestException('分类不存在');
      }

      video.category = category;
    }

    // 保存更新
    await this.videoRepository.save(video);

    return {
      code: 200,
      message: '管理员更新视频信息成功',
      data: {
        video_id: video.video_id,
        title: video.title,
        description: video.description,
        categoryId: video.category?.id || null,
        userId: video.user.id,
        username: video.user.username,
      },
    };
  }

  /**
   * @description 生成OSS上传凭证（前端直传）
   */

  generateUploadToken() {
    const options = { scope: this.configService.get('QINIU_BUCKET') };
    const putPolicy = new qiniu.rs.PutPolicy(options);
    // 返回domain
    const domain = this.configService.get('QINIU_DOMAIN');
    return {
      token: putPolicy.uploadToken(this.qiniuMac),
      domain,
    };
  }

  /**
   * @description 用户发布视频
   */
  async createVideo(createVideoDto: CreateVideoDto, UserId: string) {
    // 验证分类是否存在
    const category = await this.videoCategoryRepository.findOne({
      where: { id: createVideoDto.categoryId },
    });
    if (!category) {
      throw new NotFoundException(
        `ID为${createVideoDto.categoryId}的分类不存在`,
      );
    }

    // 生成OSS完整URL
    // 检查并生成OSS完整URL
    const ossVideoUrl = this.getFullUrl(createVideoDto.ossVideoKey);
    const ossCoverUrl = this.getFullUrl(createVideoDto.ossCoverKey);

    const video = this.videoRepository.create({
      title: createVideoDto.title,
      description: createVideoDto.description,
      oss_url: ossVideoUrl,
      cover_url: ossCoverUrl,
      duration: createVideoDto.duration || 0,
      status: 'pending',
      user: { id: parseInt(UserId) }, // 将string类型转换为number类型
      category: { id: createVideoDto.categoryId }, // 添加分类关联
    });

    // 保存视频记录
    await this.videoRepository.save(video);

    // 判断是否需要审核
    if (this.configService.get('CENSOR_ENABLE') === 'true') {
      this.startCensorProcess(
        video.video_id,
        createVideoDto.ossVideoKey,
        createVideoDto.title,
        createVideoDto.description,
      );
    } else {
      video.status = VideoStatus.APPROVED;
      await this.videoRepository.save(video);
    }

    return {
      message: '视频发布成功, 正在快马加鞭的审核...',
    };
  }

  /**
   * @description 将资源键转换为完整URL
   * @param key 资源键或URL
   * @returns 完整URL
   */
  private getFullUrl(key: string): string {
    if (!key) return '';

    // 检查是否已经是完整URL
    if (this.isValidUrl(key)) {
      return key;
    }

    // 不是完整URL，则拼接域名
    const domain = this.configService.get('QINIU_DOMAIN');
    // 确保域名末尾没有斜杠，资源键开头没有斜杠
    const formattedDomain = domain.endsWith('/') ? domain.slice(0, -1) : domain;
    const formattedKey = key.startsWith('/') ? key.substring(1) : key;

    return `${formattedDomain}/${formattedKey}`;
  }

  /**
   * @description 检查字符串是否为有效URL
   * @param url 要检查的字符串
   * @returns 是否为有效URL
   */
  private isValidUrl(url: string): boolean {
    try {
      new URL(url);
      return url.startsWith('http://') || url.startsWith('https://');
    } catch (e) {
      return false;
    }
  }

  /**
   * @description 更新审核状态
   */
  async updateVideoStatus(data: any) {
    const { jobId, result, reason } = data;
    const video = await this.videoRepository.findOne({
      where: { censor_job_id: jobId },
    });
    if (!video) return;

    if (result === 'pass' && video.status === VideoStatus.PENDING) {
      video.status = VideoStatus.APPROVED;
    } else {
      video.status = VideoStatus.REJECTED;
      video.audit_reason = reason || '视频内容违规';
    }

    await this.videoRepository.save(video);
  }

  /**
   * @description 发布视频审核流程
   */
  private async startCensorProcess(
    videoId: number,
    ossKey: string,
    title: string,
    description: string,
  ) {
    try {
      // 1. 审核文本（同步）
      const isTextValid = await this.censorText(title, description);
      if (!isTextValid) {
        await this.videoRepository.update(videoId, {
          status: VideoStatus.REJECTED,
          audit_reason: '标题或描述包含违规内容',
        });
        return;
      }

      // 2. 触发视频审核（异步）
      const callbackUrl = 'https://your-domain.com/video/censor-callback';
      const jobId = await this.qiniuService.censorVideo(
        ossKey,
        videoId,
        callbackUrl,
      );

      // 保存jobId到数据库（用于回调匹配）
      await this.videoRepository.update(videoId, { censor_job_id: jobId });
    } catch (error) {
      // 错误处理 & 重试逻辑
      console.error('审核失败', error);
      throw error;
    }
  }

  /**
   * @description 审核文本内容
   */
  private async censorText(
    title: string,
    description: string,
  ): Promise<boolean> {
    try {
      const titleValid = await this.qiniuService.censorText(title);
      const descValid = await this.qiniuService.censorText(description);
      console.log('titleValid', titleValid);
      console.log('descValid', descValid);
      // return titleValid && descValid;
      return true;
    } catch (error) {
      // 可降级为人工审核
      return false;
    }
  }

  /**
   * @description 删除视频
   */
  async remove(id: number) {
    const video = await this.videoRepository.findOne({
      where: [{ video_id: id }],
    });
    if (!video) {
      return {
        message: '视频不存在',
      };
    }
    // 使用逻辑删除
    // 逻辑删除
    video.is_delete = 1;
    await this.videoRepository.save(video);

    return {
      message: '删除成功',
    };
  }

  /**
   * @description 更新视频点赞数
   */
  async updateLikeCount(videoId: number, count: number) {
    await this.videoRepository.update(
      { video_id: videoId },
      { likes_count: count },
    );
  }

  async getVideos(currentUserId?: string) {
    // 接收当前用户ID（可选）
    // 1. 从MySQL查询基础信息
    const videos = await this.videoRepository.find();

    // 2. 批量获取Redis点赞数
    const videoIds = videos.map((v) => String(v.video_id));
    const likes = await this.redis.hmget('video_likes', ...videoIds);

    // 3. 获取当前用户点赞状态（如果用户已登录）
    let userLikedVideoIds: string[] = [];
    if (currentUserId) {
      userLikedVideoIds = await this.redis.smembers(
        `user_likes:${currentUserId}`,
      );
    }

    // 4. 合并数据
    return videos.map((video, index) => ({
      ...video,
      like_count: parseInt(likes[index]) || 0,
      is_liked: userLikedVideoIds.includes(String(video.video_id)), // 判断是否点赞
    }));
  }

  /**
   * 获取用户的视频列表
   * @param userId 要查询的用户ID
   * @param currentUserId 当前登录用户ID
   * @param queryParams 查询参数
   * @returns 包含分页信息的视频列表
   */
  async getUserVideos(
    userId: number,
    currentUserId: number | undefined,
    queryParams: GetUserVideosDto,
  ) {
    const { page, limit, status, keyword } = queryParams;
    const isOwnProfile = currentUserId && userId === currentUserId;

    // 构建基本查询
    const queryBuilder = this.videoRepository
      .createQueryBuilder('video')
      .leftJoinAndSelect('video.user', 'user')
      .leftJoinAndSelect('video.category', 'category')
      .where('user.id = :userId', { userId })
      .andWhere('video.is_delete = 0');

    // 关键词搜索处理
    if (keyword && keyword.trim()) {
      const searchKeyword = `%${keyword.trim()}%`;
      queryBuilder.andWhere(
        '(video.title LIKE :keyword OR category.name LIKE :keyword)',
        { keyword: searchKeyword },
      );
    }

    // 状态过滤
    if (status !== VideoStatusFilter.ALL) {
      if (status === 'pending') {
        // 如果状态是pending，同时返回pending和manualReview状态的视频
        queryBuilder.andWhere(
          '(video.status = :status OR video.status = :manualReviewStatus)',
          {
            status: 'pending',
            manualReviewStatus: 'manualReview',
          },
        );
      } else {
        // 其他状态正常查询
        queryBuilder.andWhere('video.status = :status', { status });
      }
    } else if (!isOwnProfile) {
      // 如果查看他人视频，只能查看已审核通过且非隐藏的视频
      queryBuilder.andWhere('video.status = :status', { status: 'approved' });
    }

    // 如果不是查看自己的视频，需要过滤掉隐藏的视频
    if (!isOwnProfile) {
      queryBuilder.andWhere('video.status != :hiddenStatus', {
        hiddenStatus: 'hidden',
      });
    }

    // 计算总数
    const total = await queryBuilder.getCount();

    // 分页和排序
    queryBuilder
      .orderBy('video.created_at', 'DESC')
      .skip((page - 1) * limit)
      .take(limit);

    // 执行查询
    const videos = await queryBuilder.getMany();

    // 如果有当前用户ID，获取点赞状态
    if (currentUserId) {
      const videoIds = videos.map((v) => v.video_id.toString());
      await this.addLikeInfoToVideos(
        videos,
        currentUserId.toString(),
        videoIds,
      );
    }

    return {
      data: videos,
      pagination: {
        total,
        page,
        limit,
        totalPages: Math.ceil(total / limit),
      },
    };
  }

  /**
   * 为视频数据添加点赞信息
   */
  public async addLikeInfoToVideos(
    videos: Video[],
    userId: string,
    videoIds: string[],
  ) {
    // 如果没有视频或视频ID，直接返回
    if (!videoIds.length) return videos;

    // 批量获取Redis点赞数
    const likes = await this.redis.hmget('video_likes', ...videoIds);

    // 获取当前用户点赞状态
    let userLikedVideoIds: string[] = [];
    if (userId) {
      userLikedVideoIds = await this.redis.smembers(`user_likes:${userId}`);
    }

    // 将点赞信息添加到视频对象
    videos.forEach((video, index) => {
      const videoId = video.video_id.toString();
      (video as any).like_count =
        parseInt(likes[index]) || video.likes_count || 0;
      (video as any).is_liked = userLikedVideoIds.includes(videoId);
    });

    return videos;
  }

  // 在VideoService中实现
  async getUserPublicVideos(
    userId: number,
    currentUserId: number | undefined,
    page: number = 1,
    limit: number = 10,
  ) {
    // 构建查询
    const queryBuilder = this.videoRepository
      .createQueryBuilder('video')
      .leftJoinAndSelect('video.user', 'user')
      .leftJoinAndSelect('video.category', 'category')
      .where('user.id = :userId', { userId })
      .andWhere('video.status = :status', { status: VideoStatus.APPROVED })
      .andWhere('video.is_delete = 0')
      .orderBy('video.created_at', 'DESC')
      .skip((page - 1) * limit)
      .take(limit);

    // 执行查询
    const [videos, total] = await queryBuilder.getManyAndCount();

    // 添加点赞信息
    if (currentUserId && videos.length > 0) {
      const videoIds = videos.map((v) => v.video_id.toString());
      await this.addLikeInfoToVideos(
        videos,
        currentUserId.toString(),
        videoIds,
      );
    }

    return {
      data: videos,
      pagination: {
        total,
        page,
        limit,
        totalPages: Math.ceil(total / limit),
      },
    };
  }

  /**
   * 更新视频信息
   * @param id 视频ID
   * @param updateVideoDto 更新视频DTO
   * @param userId 当前用户ID
   */
  async updateVideo(
    id: number,
    updateVideoDto: UpdateVideoDto,
    userId: number,
  ) {
    // 查找视频
    const video = await this.videoRepository.findOne({
      where: { video_id: id, is_delete: 0 },
      relations: ['user'],
    });

    // 视频不存在或已删除
    if (!video) {
      throw new NotFoundException('视频不存在或已删除');
    }

    // 检查权限（只有视频作者可以修改）
    if (video.user.id !== userId) {
      throw new ForbiddenException('您没有权限修改该视频');
    }

    // 更新视频信息
    if (updateVideoDto.title) {
      video.title = updateVideoDto.title;
    }

    if (updateVideoDto.description) {
      video.description = updateVideoDto.description;
    }

    // 更新分类
    if (updateVideoDto.categoryId) {
      const category = await this.videoCategoryRepository.findOne({
        where: { id: updateVideoDto.categoryId },
      });

      if (!category) {
        throw new BadRequestException('分类不存在');
      }

      video.category = category;
    }

    // 保存更新
    await this.videoRepository.save(video);

    return {
      code: 200,
      message: '更新视频信息成功',
      data: {
        video_id: video.video_id,
        title: video.title,
        description: video.description,
        categoryId: video.category?.id || null,
      },
    };
  }

  /**
   * 切换视频可见性（公开/隐藏）
   * @param id 视频ID
   * @param isPublic 是否公开 (true-公开, false-隐藏)
   * @param userId 当前用户ID
   */
  async toggleVideoVisibility(id: number, isPublic: boolean, userId: number) {
    // 查找视频
    const video = await this.videoRepository.findOne({
      where: { video_id: id, is_delete: 0 },
      relations: ['user'],
    });

    // 视频不存在或已删除
    if (!video) {
      throw new NotFoundException('视频不存在或已删除');
    }

    // 检查权限（只有视频作者可以修改）
    if (video.user.id !== userId) {
      throw new ForbiddenException('您没有权限修改该视频');
    }

    // 只有已审核通过的视频才能切换可见性
    if (video.status == 'pending') {
      throw new BadRequestException('只有审核通过的视频才能设置可见性');
    }

    // 更新视频状态
    video.status = isPublic ? 'approved' : 'hidden';

    // 保存更新
    await this.videoRepository.save(video);

    return {
      code: 200,
      message: isPublic ? '视频已设为公开' : '视频已设为隐藏',
      data: {
        video_id: video.video_id,
        title: video.title,
        status: video.status,
        isPublic: video.status === 'approved',
      },
    };
  }

  /**
   * 重新提交审核不通过的视频
   * @param id 视频ID
   * @param resubmitVideoDto 重新提交视频DTO
   * @param userId 当前用户ID
   */
  async resubmitVideo(
    id: number,
    resubmitVideoDto: ResubmitVideoDto,
    userId: number,
  ) {
    // 查找视频
    const video = await this.videoRepository.findOne({
      where: { video_id: id, is_delete: 0 },
      relations: ['user'],
    });

    // 视频不存在或已删除
    if (!video) {
      throw new NotFoundException('视频不存在或已删除');
    }

    // 检查权限（只有视频作者可以修改）
    if (video.user.id !== userId) {
      throw new ForbiddenException('您没有权限修改该视频');
    }

    // 只有审核拒绝的视频才能重新提交
    if (video.status !== 'rejected') {
      throw new BadRequestException('只有审核不通过的视频才能重新提交审核');
    }

    // 更新视频信息
    if (resubmitVideoDto.title) {
      video.title = resubmitVideoDto.title;
    }

    if (resubmitVideoDto.description) {
      video.description = resubmitVideoDto.description;
    }

    if (resubmitVideoDto.oss_url) {
      video.oss_url = resubmitVideoDto.oss_url;
    }

    if (resubmitVideoDto.cover_url) {
      video.cover_url = resubmitVideoDto.cover_url;
    }

    // 重置审核状态为待审核
    video.status = 'pending';
    // 清空拒绝原因
    video.audit_reason = null;

    // 如果视频URL发生变化，需要重新提交审核任务
    let censorJobId = null;
    if (resubmitVideoDto.oss_url) {
      try {
        // 提交新的审核任务
        const censorResult = await this.submitVideoReview(video.oss_url);
        censorJobId = censorResult.jobId || null;
      } catch (error) {
        console.error('提交视频审核失败', error);
        throw new InternalServerErrorException('提交审核失败，请稍后重试');
      }
    }

    // 更新审核任务ID（如果有）
    if (censorJobId) {
      video.censor_job_id = censorJobId;
    }

    // 保存更新
    await this.videoRepository.save(video);

    return {
      code: 200,
      message: '重新提交审核成功，请等待审核结果',
      data: {
        video_id: video.video_id,
        title: video.title,
        status: video.status,
      },
    };
  }

  /**
   * 提交视频进行内容审核
   * @param videoUrl 视频URL
   * @returns 包含jobId的审核任务结果
   */
  private async submitVideoReview(videoUrl: string) {
    try {
      // 确保使用完整的URL
      const fullVideoUrl = this.getFullUrl(videoUrl);

      // 获取回调URL
      const callbackUrl = `${this.configService.get('API_BASE_URL', 'http://localhost:3000')}/video/censorCallBack`;

      // 调用七牛云审核服务
      const jobId = await this.qiniuService.censorVideo(
        fullVideoUrl,
        0, // 这里可以传0，因为我们已经有视频记录
        callbackUrl,
      );

      return {
        success: true,
        jobId: jobId,
      };
    } catch (error) {
      console.error('提交视频审核失败:', error);
      throw new InternalServerErrorException('无法提交视频审核，请联系管理员');
    }
  }

  /**
   * 随机获取指定数量的视频
   * @param count 需要获取的视频数量
   * @param currentUserId 当前用户ID（可选）
   * @returns 随机视频列表
   */
  // 修改getRandomVideos方法
  async getRandomVideos(count: number, currentUserId?: number): Promise<any> {
    // 确保 count 是有效的正整数
    const limit = Math.max(1, Math.min(count, 20)); // 限制最大数量为20

    // 获取所有已审核通过且非隐藏的视频总数
    const totalVideos = await this.videoRepository.count({
      where: {
        status: VideoStatus.APPROVED,
        is_delete: 0,
      },
    });

    if (totalVideos === 0) {
      return {
        code: 200,
        data: [],
        message: '暂无可用视频',
      };
    }

    // 随机获取指定数量的视频
    const randomVideos = await this.videoRepository
      .createQueryBuilder('video')
      .leftJoinAndSelect('video.user', 'user')
      .leftJoinAndSelect('video.category', 'category')
      .select([
        'video.video_id',
        'video.title',
        'video.description',
        'video.cover_url',
        'video.oss_url',
        'video.likes_count',
        'video.duration',
        'video.created_at',
        'user.id',
        'user.username',
        'user.avatar',
        'category.id',
        'category.name',
      ])
      .where('video.status = :status', { status: VideoStatus.APPROVED })
      .andWhere('video.is_delete = 0')
      .orderBy('RAND()') // MySQL使用RAND()，PostgreSQL使用RANDOM()
      .take(limit)
      .getMany();

    // 获取视频ID列表
    const videoIds = randomVideos.map((video) => video.video_id.toString());

    if (videoIds.length === 0) {
      return {
        code: 200,
        data: [],
        message: '暂无可用视频',
      };
    }

    // 如果有当前用户ID，获取点赞状态
    let userLikedVideoIds: string[] = [];
    if (currentUserId && videoIds.length > 0) {
      userLikedVideoIds = await this.redis.smembers(
        `user_likes:${currentUserId}`,
      );
    }

    // 批量获取Redis中的点赞数
    let redisLikeCounts: string[] = [];
    if (videoIds.length > 0) {
      redisLikeCounts = await this.redis.hmget('video_likes', ...videoIds);
    }

    // 获取每个视频的评论数
    const commentCounts = await this.dataSource
      .getRepository(Comment)
      .createQueryBuilder('comment')
      .select('comment.videoId', 'videoId')
      .addSelect('COUNT(comment.id)', 'count')
      .where('comment.videoId IN (:...videoIds)', { videoIds })
      .andWhere('comment.deletedAt IS NULL')
      .groupBy('comment.videoId')
      .getRawMany();

    // 构建评论数映射
    const commentCountMap = new Map();
    commentCounts.forEach((item) => {
      commentCountMap.set(item.videoId, parseInt(item.count));
    });

    // 获取每个视频的收藏数
    const favoriteCounts = await this.dataSource
      .createQueryBuilder()
      .select('favorite_video.video_id')
      .addSelect('COUNT(*)', 'count')
      .from(FavoriteVideo, 'favorite_video')
      .leftJoin('favorite_video.favorite', 'favorite')
      .where('favorite_video.video_id IN (:...videoIds)', { videoIds })
      .andWhere('favorite.is_delete = 0') // 只计算未删除的收藏夹
      .groupBy('favorite_video.video_id')
      .getRawMany();

    // 构建收藏数映射
    const favoriteCountMap = new Map();
    favoriteCounts.forEach((item) => {
      favoriteCountMap.set(item.video_id, parseInt(item.count));
    });

    // 获取当前用户收藏的视频
    let userFavoritedVideoIds: number[] = [];
    if (currentUserId && videoIds.length > 0) {
      // 查询当前用户所有收藏夹中收藏的视频
      const userFavorites = await this.dataSource
        .createQueryBuilder()
        .select('favorite_video.video_id')
        .from(FavoriteVideo, 'favorite_video')
        .innerJoin('favorite_video.favorite', 'favorite')
        .where('favorite.user.id = :userId', { userId: currentUserId })
        .andWhere('favorite_video.video_id IN (:...videoIds)', { videoIds })
        .andWhere('favorite.is_delete = 0')
        .getRawMany();

      userFavoritedVideoIds = userFavorites.map((item) =>
        parseInt(item.video_id),
      );
    }

    // 获取当前用户关注的用户列表
    let followingUserIds: number[] = [];
    if (currentUserId) {
      followingUserIds =
        await this.followService.getFollowingIds(currentUserId);
    }

    // 转换结果并添加所需字段
    const enhancedVideos = randomVideos.map((video, index) => {
      // 获取Redis中的实时点赞数，如果没有则使用数据库中的备份值
      const likeCount =
        parseInt(redisLikeCounts[index]) || video.likes_count || 0;
      const videoId = video.video_id;
      const authorId = video.user.id;

      return {
        ...video,
        likeCount,
        commentCount: commentCountMap.get(videoId) || 0, // 实际评论数
        favoritesCount: favoriteCountMap.get(videoId) || 0, // 实际收藏数
        isLiked: currentUserId
          ? userLikedVideoIds.includes(videoId.toString())
          : false, // 当前用户是否已点赞
        isFavorited: currentUserId
          ? userFavoritedVideoIds.includes(videoId)
          : false, // 当前用户是否已收藏
        isFollowed: currentUserId ? followingUserIds.includes(authorId) : false, // 当前用户是否已关注视频作者
      };
    });

    return {
      code: 200,
      data: enhancedVideos,
      message: '获取随机视频成功',
    };
  }

  /**
   * 获取单个视频的详细信息
   * @param id 视频ID
   * @param currentUserId 当前用户ID（可选）
   * @returns 视频详情
   */
  async getVideoDetails(id: number, currentUserId?: number): Promise<any> {
    // 查询视频信息
    const video = await this.videoRepository
      .createQueryBuilder('video')
      .leftJoinAndSelect('video.user', 'user')
      .leftJoinAndSelect('video.category', 'category')
      .select([
        'video.video_id',
        'video.title',
        'video.description',
        'video.cover_url',
        'video.oss_url',
        'video.likes_count',
        'video.duration',
        'video.created_at',
        'video.status', // 添加状态字段
        'user.id',
        'user.username',
        'user.avatar',
        'category.id',
        'category.name',
      ])
      .where('video.video_id = :videoId', { videoId: id })
      .andWhere('video.is_delete = 0')
      .getOne();

    // 如果视频不存在
    if (!video) {
      throw new NotFoundException('视频不存在或已被删除');
    }

    // 如果视频未审核通过且当前用户不是视频作者，则无权查看
    if (video.status !== VideoStatus.APPROVED) {
      throw new ForbiddenException('该视频尚未审核通过或已被隐藏');
    }

    // 获取视频ID
    const videoId = video.video_id.toString();

    // 获取用户点赞状态
    let isLiked = false;
    if (currentUserId) {
      const userLikedVideos = await this.redis.smembers(
        `user_likes:${currentUserId}`,
      );
      isLiked = userLikedVideos.includes(videoId);
    }

    // 获取Redis中的点赞数，如果没有则使用数据库中的备份值
    const redisLikeCount = await this.redis.hget('video_likes', videoId);
    const likeCount = parseInt(redisLikeCount) || video.likes_count || 0;

    // 获取评论数
    const commentCount = await this.dataSource
      .getRepository(Comment)
      .createQueryBuilder('comment')
      .where('comment.videoId = :videoId', { videoId })
      .andWhere('comment.deletedAt IS NULL')
      .getCount();

    // 获取收藏数
    const favoriteCount = await this.dataSource
      .createQueryBuilder()
      .select('COUNT(*)', 'count')
      .from(FavoriteVideo, 'favorite_video')
      .leftJoin('favorite_video.favorite', 'favorite')
      .where('favorite_video.video_id = :videoId', { videoId })
      .andWhere('favorite.is_delete = 0')
      .getRawOne();

    // 检查当前用户是否已收藏该视频
    let isFavorited = false;
    if (currentUserId) {
      const favoritedVideo = await this.dataSource
        .createQueryBuilder()
        .select('favorite_video.id')
        .from(FavoriteVideo, 'favorite_video')
        .innerJoin('favorite_video.favorite', 'favorite')
        .where('favorite.user.id = :userId', { userId: currentUserId })
        .andWhere('favorite_video.video_id = :videoId', { videoId })
        .andWhere('favorite.is_delete = 0')
        .getRawOne();

      isFavorited = !!favoritedVideo;
    }

    // 检查当前用户是否已关注视频作者
    let isFollowed = false;
    if (currentUserId && currentUserId !== video.user.id) {
      const followingIds =
        await this.followService.getFollowingIds(currentUserId);
      isFollowed = followingIds.includes(video.user.id);
    }

    // 组装结果
    const result = {
      ...video,
      likeCount,
      commentCount,
      favoritesCount: parseInt(favoriteCount?.count || '0'),
      isLiked,
      isFavorited,
      isFollowed,
    };

    return {
      code: 200,
      data: result,
      message: '获取视频详情成功',
    };
  }

  /**
   * 管理员下架视频
   * @param id 视频ID
   * @param reason 下架理由
   * @returns 操作结果
   */
  async rejectVideo(id: number, reason: string) {
    // 查找视频
    const video = await this.videoRepository.findOne({
      where: { video_id: id, is_delete: 0 },
      relations: ['user'],
    });

    // 视频不存在或已删除
    if (!video) {
      throw new NotFoundException('视频不存在或已删除');
    }

    // 只有已审核通过或人工审核状态的视频才能被下架
    if (
      video.status !== VideoStatus.APPROVED &&
      video.status !== 'manualReview'
    ) {
      throw new BadRequestException(
        '只有已审核通过或人工审核状态的视频才能被下架',
      );
    }

    // 更新视频状态
    video.status = VideoStatus.REJECTED;
    video.audit_reason = reason;

    // 保存更新
    await this.videoRepository.save(video);

    return {
      code: 200,
      message: '视频已成功下架',
      data: {
        video_id: video.video_id,
        title: video.title,
        status: video.status,
        reason: video.audit_reason,
      },
    };
  }
}
